#include "esp8266.h"
#include "common.h"
#include <stdio.h>  
#include <string.h>  
#include <stdbool.h>
#include "Delay.h"
#include "usart.h"

volatile uint8_t ucTcpClosedFlag = 0;

char cStr [ 1500 ] = { 0 };
static void                   ESP8266_GPIO_Config                 ( void );
static void                   ESP8266_USART_Config                ( void );
static void                   ESP8266_USART_NVIC_Configuration    ( void );
struct  STRUCT_USARTx_Fram strEsp8266_Fram_Record = { 0 };



/**
  * @brief  MQTT用户配置
  */
void MQTT_UserCfg(void)
{
    char cmd[256];
    
    // 配置MQTT用户参数
    sprintf(cmd, "AT+MQTTUSERCFG=0,1,\"%s\",\"%s\",\"%s\",0,0,\"\"", 
            THINGSCLOUD_DEVICE_ID, 
            THINGSCLOUD_ACCESS_TOKEN, 
            THINGSCLOUD_PROJECT_KEY);
    
    ESP8266_Cmd(cmd, "OK", NULL, 3000);
    
    Usart_SendString(USART1, "MQTT User Config Done\r\n");
}

/**
  * @brief  MQTT连接
  */
void MQTT_Connect(void)
{
    char cmd[150];
    
    sprintf(cmd, "AT+MQTTCONN=0,\"%s\",%s,1", 
            THINGSCLOUD_MQTT_HOST, 
            THINGSCLOUD_MQTT_PORT);
    
    if(ESP8266_Cmd(cmd, "+MQTTCONNECTED", "OK", 10000)) {
        Usart_SendString(USART1, "MQTT Connected Successfully\r\n");
    } else {
        Usart_SendString(USART1, "MQTT Connect Failed\r\n");
    }
}

/**
  * @brief  MQTT发布消息
  * @param  topic: 主题
  * @param  message: 消息内容
  * @retval 发布是否成功
  */
bool MQTT_Publish(const char *topic, const char *message)
{
    char cmd[512];
    
    // JSON格式
    sprintf(cmd, "AT+MQTTPUB=0,\"%s\",\"%s\",0,0", topic, message);
    
    return ESP8266_Cmd(cmd, "OK", NULL, 3000);
}


/**
  * @brief  订阅MQTT控制命令主题
  */
void MQTT_Subscribe_Commands(void)
{
    // 订阅控制命令主题
    ESP8266_Cmd("AT+MQTTSUB=0,\"attributes/push\",1", "OK", NULL, 3000);
    Usart_SendString(USART1, "MQTT Command Subscription Done\r\n");
}

/**
  * @brief  解析和处理MQTT控制命令
  */
void MQTT_Command_Process(void)
{
    char *pch;
    char json_buffer[256];
    
    // 检查是否收到MQTT订阅消息
    pch = strstr(strEsp8266_Fram_Record.Data_RX_BUF, "+MQTTSUBRECV");
    if(pch != NULL)
    {
        Usart_SendString(USART1, "MQTT Command Received: ");
        Usart_SendString(USART1, strEsp8266_Fram_Record.Data_RX_BUF);
        Usart_SendString(USART1, "\r\n");
        
        // 提取JSON数据部分
        pch = strstr(strEsp8266_Fram_Record.Data_RX_BUF, "{");
        if(pch != NULL)
        {
            strncpy(json_buffer, pch, sizeof(json_buffer)-1);
            json_buffer[sizeof(json_buffer)-1] = '\0';
            
            // 解析控制命令
            if(strstr(json_buffer, "\"light_state\":true"))
            {
                // 打开LED灯
                CloudControl_LED(true);
                Usart_SendString(USART1, "LED Turned ON by Cloud\r\n");
            }
            else if(strstr(json_buffer, "\"light_state\":false"))
            {
                // 关闭LED灯
                CloudControl_LED(false);
                Usart_SendString(USART1, "LED Turned OFF by Cloud\r\n");
            }
            
            if(strstr(json_buffer, "\"buzzer_state\":true"))
            {
                // 打开蜂鸣器
                CloudControl_Buzzer(true);
                Usart_SendString(USART1, "Buzzer Turned ON by Cloud\r\n");
            }
            else if(strstr(json_buffer, "\"buzzer_state\":false"))
            {
                // 关闭蜂鸣器
                CloudControl_Buzzer(false);
                Usart_SendString(USART1, "Buzzer Turned OFF by Cloud\r\n");
            }
            
            if(strstr(json_buffer, "\"motor_switch\":true"))
            {
                // 打开电机
                CloudControl_Motor(true);
                Usart_SendString(USART1, "Motor Turned ON by Cloud\r\n");
            }
            else if(strstr(json_buffer, "\"motor_switch\":false"))
            {
                // 关闭电机
                CloudControl_Motor(false);
                Usart_SendString(USART1, "Motor Turned OFF by Cloud\r\n");
            }
        }
        
        // 清除已处理的数据
        strEsp8266_Fram_Record.InfBit.FramLength = 0;
        memset(strEsp8266_Fram_Record.Data_RX_BUF, 0, RX_BUF_MAX_LEN);
    }
}


/**
  * @brief  MQTT初始化
  */
void MQTT_Init(void)
{
    Usart_SendString(USART1, "Starting MQTT Init...\r\n");
    
    // MQTT用户配置
    MQTT_UserCfg();
    Delay_ms(1000);
    
    // 连接MQTT服务器
    MQTT_Connect();
    Delay_ms(2000);
	
	    // 订阅控制命令主题
    MQTT_Subscribe_Commands();
}


/**
  * @brief  ESP8266 Sta Tcp Clien
  */
void ESP8266_StaTcpClient ( void )
{
    printf ( "\r\n ESP8266 MQTT Client Starting...\r\n" );

    // 基础AT测试
    ESP8266_AT_Test ();
    
    // 设置STA模式
    ESP8266_Net_Mode_Choose ( STA );

    // 连接WiFi
    while ( ! ESP8266_JoinAP ( macUser_ESP8266_ApSsid, macUser_ESP8266_ApPwd ) ) {
        Usart_SendString(USART1, "WiFi Connect Failed, Retrying...\r\n");
        Delay_ms(2000);
    }
    
    Usart_SendString(USART1, "WiFi Connected Successfully\r\n");
    
    // 显示IP地址
    ESP8266_Cmd ( "AT+CIFSR", "OK", NULL, 1000 );
    
    // 初始化MQTT
    MQTT_Init();
}


void ESP8266_Init ( void )
{
//	ESP8266_GPIO_Config (); 
	
	ESP8266_USART_Config (); 
	
	
//	macESP8266_RST_HIGH_LEVEL();

//	macESP8266_CH_DISABLE();
	
	
}


/**
  * @brief  ESP8266  GPIO
  */
static void ESP8266_GPIO_Config ( void )
{

	GPIO_InitTypeDef GPIO_InitStructure;


	macESP8266_CH_PD_APBxClock_FUN ( macESP8266_CH_PD_CLK, ENABLE ); 
											   
	GPIO_InitStructure.GPIO_Pin = macESP8266_CH_PD_PIN;	

	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;   
   
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 

	GPIO_Init ( macESP8266_CH_PD_PORT, & GPIO_InitStructure );	 

	macESP8266_RST_APBxClock_FUN ( macESP8266_RST_CLK, ENABLE ); 
											   
	GPIO_InitStructure.GPIO_Pin = macESP8266_RST_PIN;	

	GPIO_Init ( macESP8266_RST_PORT, & GPIO_InitStructure );	 


}


/**
  * @brief  ESP8266 USART
  */
static void ESP8266_USART_Config ( void )
{
	GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	
	
	/* config USART clock */
	macESP8266_USART_APBxClock_FUN ( macESP8266_USART_CLK, ENABLE );
	macESP8266_USART_GPIO_APBxClock_FUN ( macESP8266_USART_GPIO_CLK, ENABLE );
	
	/* USART GPIO config */
	/* Configure USART Tx as alternate function push-pull */
	GPIO_InitStructure.GPIO_Pin =  macESP8266_USART_TX_PIN;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(macESP8266_USART_TX_PORT, &GPIO_InitStructure);  
  
	/* Configure USART Rx as input floating */
	GPIO_InitStructure.GPIO_Pin = macESP8266_USART_RX_PIN;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	GPIO_Init(macESP8266_USART_RX_PORT, &GPIO_InitStructure);
	
	/* USART1 mode config */
	USART_InitStructure.USART_BaudRate = macESP8266_USART_BAUD_RATE;
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;
	USART_InitStructure.USART_StopBits = USART_StopBits_1;
	USART_InitStructure.USART_Parity = USART_Parity_No ;
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
	USART_Init(macESP8266_USARTx, &USART_InitStructure);
	
	
	USART_ITConfig ( macESP8266_USARTx, USART_IT_RXNE, ENABLE );
	USART_ITConfig ( macESP8266_USARTx, USART_IT_IDLE, ENABLE );	

	ESP8266_USART_NVIC_Configuration ();
	
	
	USART_Cmd(macESP8266_USARTx, ENABLE);
	
	
}


/**
  * @brief   ESP8266 USART  NVIC 
  */
static void ESP8266_USART_NVIC_Configuration ( void )
{
	NVIC_InitTypeDef NVIC_InitStructure; 
	
	    // 确保使用正确的优先级分组
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    
    /* 修改这里：降低ESP8266串口中断优先级 */
    NVIC_InitStructure.NVIC_IRQChannel = macESP8266_USART_IRQ;     
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;  // 改为2（原来是0）
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;         // 子优先级
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
	
//	/* Configure the NVIC Preemption Priority Bits */  
//	NVIC_PriorityGroupConfig ( macNVIC_PriorityGroup_x );

//	/* Enable the USART2 Interrupt */
//	NVIC_InitStructure.NVIC_IRQChannel = macESP8266_USART_IRQ;	 
//	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
//	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
//	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
//	NVIC_Init(&NVIC_InitStructure);

}


/*
 * ESP8266_Rst
 * WF-ESP8266
 ESP8266_AT_Test 
 */
void ESP8266_Rst ( void )
{
	#if 0
	 ESP8266_Cmd ( "AT+RST", "OK", "ready", 2500 );   	
	
	#else
	 macESP8266_RST_LOW_LEVEL();
	 Delay_ms ( 500 ); 
	 macESP8266_RST_HIGH_LEVEL();
	#endif

}


bool ESP8266_Cmd ( char * cmd, char * reply1, char * reply2, u32 waittime )
{    
	strEsp8266_Fram_Record .InfBit .FramLength = 0;      

	macESP8266_Usart ( "%s\r\n", cmd );

	if ( ( reply1 == 0 ) && ( reply2 == 0 ) )                    
		return true;
	
	Delay_ms( waittime );    
	
	strEsp8266_Fram_Record .Data_RX_BUF [ strEsp8266_Fram_Record .InfBit .FramLength ]  = '\0';

	macPC_Usart ( "%s", strEsp8266_Fram_Record .Data_RX_BUF );
  
	if ( ( reply1 != 0 ) && ( reply2 != 0 ) )
		return ( ( bool ) strstr ( strEsp8266_Fram_Record .Data_RX_BUF, reply1 ) || 
						 ( bool ) strstr ( strEsp8266_Fram_Record .Data_RX_BUF, reply2 ) ); 
 	
	else if ( reply1 != 0 )
		return ( ( bool ) strstr ( strEsp8266_Fram_Record .Data_RX_BUF, reply1 ) );
	
	else
		return ( ( bool ) strstr ( strEsp8266_Fram_Record .Data_RX_BUF, reply2 ) );
	
}




void ESP8266_AT_Test ( void )
{
	char count=0;
	
	macESP8266_RST_HIGH_LEVEL();	
	Delay_ms( 1000 );
	while ( count < 10 )
	{
		if( ESP8266_Cmd ( "AT", "OK", NULL, 500 ) ) return;
		ESP8266_Rst();
		++ count;
	}
}


bool ESP8266_Net_Mode_Choose ( ENUM_Net_ModeTypeDef enumMode )
{
	switch ( enumMode )
	{
		case STA:
			return ESP8266_Cmd ( "AT+CWMODE=1", "OK", "no change", 2500 ); 
		
	  case AP:
		  return ESP8266_Cmd ( "AT+CWMODE=2", "OK", "no change", 2500 ); 
		
		case STA_AP:
		  return ESP8266_Cmd ( "AT+CWMODE=3", "OK", "no change", 2500 ); 
		
	  default:
		  return false;
  }
	
}



bool ESP8266_JoinAP ( char * pSSID, char * pPassWord )
{
	char cCmd [120];

	sprintf ( cCmd, "AT+CWJAP=\"%s\",\"%s\"", pSSID, pPassWord );
	
	return ESP8266_Cmd ( cCmd, "OK", NULL, 5000 );
	
}


bool ESP8266_BuildAP ( char * pSSID, char * pPassWord, ENUM_AP_PsdMode_TypeDef enunPsdMode )
{
	char cCmd [120];

	sprintf ( cCmd, "AT+CWSAP=\"%s\",\"%s\",1,%d", pSSID, pPassWord, enunPsdMode );
	
	return ESP8266_Cmd ( cCmd, "OK", 0, 1000 );
	
}


bool ESP8266_Enable_MultipleId ( FunctionalState enumEnUnvarnishTx )
{
	
	return ESP8266_Cmd ( "AT+CIPMUX=%d", "OK", 0, 500 );
	
}


bool ESP8266_Link_Server ( ENUM_NetPro_TypeDef enumE, char * ip, char * ComNum, ENUM_ID_NO_TypeDef id)
{
	char cStr [100] = { 0 }, cCmd [120];

  switch (  enumE )
  {
		case enumTCP:
		  sprintf ( cStr, "\"%s\",\"%s\",%s", "TCP", ip, ComNum );
		  break;
		
		case enumUDP:
		  sprintf ( cStr, "\"%s\",\"%s\",%s", "UDP", ip, ComNum );
		  break;
		
		default:
			break;
  }

  if ( id < 5 )
    sprintf ( cCmd, "AT+CIPSTART=%d,%s", id, cStr);

  else
	  sprintf ( cCmd, "AT+CIPSTART=%s", cStr );

	return ESP8266_Cmd ( cCmd, "OK", "ALREAY CONNECT", 4000 );
	
}



bool ESP8266_StartOrShutServer ( FunctionalState enumMode, char * pPortNum, char * pTimeOver )
{
	char cCmd1 [120], cCmd2 [120];

	if ( enumMode )
	{
		sprintf ( cCmd1, "AT+CIPSERVER=%d,%s", 1, pPortNum );
		
		sprintf ( cCmd2, "AT+CIPSTO=%s", pTimeOver );

		return ( ESP8266_Cmd ( cCmd1, "OK", 0, 500 ) &&
						 ESP8266_Cmd ( cCmd2, "OK", 0, 500 ) );
	}
	
	else
	{
		sprintf ( cCmd1, "AT+CIPSERVER=%d,%s", 0, pPortNum );

		return ESP8266_Cmd ( cCmd1, "OK", 0, 500 );
	}
	
}


uint8_t ESP8266_Get_LinkStatus ( void )
{
	if ( ESP8266_Cmd ( "AT+CIPSTATUS", "OK", 0, 500 ) )
	{
		if ( strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "STATUS:2\r\n" ) )
			return 2;
		
		else if ( strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "STATUS:3\r\n" ) )
			return 3;
		
		else if ( strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "STATUS:4\r\n" ) )
			return 4;		

	}
	
	return 0;
	
}


uint8_t ESP8266_Get_IdLinkStatus ( void )
{
	uint8_t ucIdLinkStatus = 0x00;
	
	
	if ( ESP8266_Cmd ( "AT+CIPSTATUS", "OK", 0, 500 ) )
	{
		if ( strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "+CIPSTATUS:0," ) )
			ucIdLinkStatus |= 0x01;
		else 
			ucIdLinkStatus &= ~ 0x01;
		
		if ( strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "+CIPSTATUS:1," ) )
			ucIdLinkStatus |= 0x02;
		else 
			ucIdLinkStatus &= ~ 0x02;
		
		if ( strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "+CIPSTATUS:2," ) )
			ucIdLinkStatus |= 0x04;
		else 
			ucIdLinkStatus &= ~ 0x04;
		
		if ( strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "+CIPSTATUS:3," ) )
			ucIdLinkStatus |= 0x08;
		else 
			ucIdLinkStatus &= ~ 0x08;
		
		if ( strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "+CIPSTATUS:4," ) )
			ucIdLinkStatus |= 0x10;
		else 
			ucIdLinkStatus &= ~ 0x10;	

	}
	
	return ucIdLinkStatus;
	
}


uint8_t ESP8266_Inquire_ApIp ( char * pApIp, uint8_t ucArrayLength )
{
	char uc;
	
	char * pCh;
	
	
  ESP8266_Cmd ( "AT+CIFSR", "OK", 0, 500 );
	
	pCh = strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "APIP,\"" );
	
	if ( pCh )
		pCh += 6;
	
	else
		return 0;
	
	for ( uc = 0; uc < ucArrayLength; uc ++ )
	{
		pApIp [ uc ] = * ( pCh + uc);
		
		if ( pApIp [ uc ] == '\"' )
		{
			pApIp [ uc ] = '\0';
			break;
		}
		
	}
	
	return 1;
	
}


//bool ESP8266_UnvarnishSend ( void )
//{
//	 ESP8266_Cmd ( "AT+CIPMODE=1", "OK", 0, 500 );
//}



void ESP8266_ExitUnvarnishSend ( void )
{
	Delay_ms( 1000 );
	
	macESP8266_Usart ( "+++" );
	
	Delay_ms( 500 ); 
	
}

bool ESP8266_SendString ( FunctionalState enumEnUnvarnishTx, char * pStr, u32 ulStrLength, ENUM_ID_NO_TypeDef ucId )
{
	char cStr [20];
	bool bRet = false;
	
		
	if ( enumEnUnvarnishTx )
	{
		macESP8266_Usart ( "%s", pStr );
		
		bRet = true;
		
	}

	else
	{
		if ( ucId < 5 )
			sprintf ( cStr, "AT+CIPSEND=%d,%d", ucId, ulStrLength + 2 );

		else
			sprintf ( cStr, "AT+CIPSEND=%d", ulStrLength + 2 );
		
		ESP8266_Cmd ( cStr, "> ", 0, 1000 );

		bRet = ESP8266_Cmd ( pStr, "SEND OK", 0, 1000 );
  }
	
	return bRet;

}


char * ESP8266_ReceiveString ( FunctionalState enumEnUnvarnishTx )
{
	char * pRecStr = 0;
	
	
	strEsp8266_Fram_Record .InfBit .FramLength = 0;
	strEsp8266_Fram_Record .InfBit .FramFinishFlag = 0;
	
	while ( ! strEsp8266_Fram_Record .InfBit .FramFinishFlag );
	strEsp8266_Fram_Record .Data_RX_BUF [ strEsp8266_Fram_Record .InfBit .FramLength ] = '\0';
	
	if ( enumEnUnvarnishTx )
		pRecStr = strEsp8266_Fram_Record .Data_RX_BUF;
	
	else 
	{
		if ( strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "+IPD" ) )
			pRecStr = strEsp8266_Fram_Record .Data_RX_BUF;

	}

	return pRecStr;
	
}




